package com.sample.command
{
	import com.sample.remote.Delegates;
	import com.sample.remote.EntityDelegate;
	import com.trg.flex.Callback;
	import com.trg.flex.FlexUtils;
	import com.trg.flex.MetaDataUtils;
	import com.trg.flex.remote.RemoteCall;
	import com.trg.flex.search.Search;
	import com.trg.flex.search.SearchResult;
	
	import flash.utils.describeType;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	
	public class EntityCommands
	{
		public static function get i():EntityCommands {
			return new EntityCommands();
		}
		
		private var delegate:EntityDelegate = Delegates.entityDelegate;
		
		public function fetch(klass:Class, id:int, callback:Callback):void {
			var call:RemoteCall = delegate.fetch(MetaDataUtils.getRemoteClass(klass), id).addResponder(callback);
			call.description = "Loading Data...";
			call.longDescription = "Fetching a specific " + MetaDataUtils.getSimpleName(klass);
			call.call();
		}
		
		public function fetchAll(klass:Class, callback:Callback):void {
			var call:RemoteCall = delegate.fetchAll(MetaDataUtils.getRemoteClass(klass)).addResponder(callback);
			call.description = "Loading Data...";
			call.longDescription = "Fetching all " + MetaDataUtils.getSimpleName(klass);
			call.call();
		}
		
		public function create(entity:Object, callback:Callback=null):void {
			var call:RemoteCall = delegate.create(entity).addResponder(callback);
			call.description = "Saving...";
			call.longDescription = "Creating a " + MetaDataUtils.getSimpleName(entity);
			call.call();
		}
		
		public function update(entity:Object, callback:Callback=null):void {
			var call:RemoteCall = delegate.update(entity).addResponder(callback);
			call.description = "Saving...";
			call.longDescription = "Saving changes to a " + MetaDataUtils.getSimpleName(entity);
			call.call();
		}
		
		public function deleteById(klass:Class, id:int, callback:Callback=null):void {
			var call:RemoteCall = delegate.deleteById(MetaDataUtils.getRemoteClass(klass), id).addResponder(callback);
			call.description = "Deleting...";
			call.longDescription = "Deleting a " + MetaDataUtils.getSimpleName(klass);
			call.call();
		}
		
		public function deleteEntity(entity:Object, callback:Callback=null):void {
			var call:RemoteCall = delegate.deleteEntity(entity).addResponder(callback);
			call.description = "Deleting...";
			call.longDescription = "Deleting a " + MetaDataUtils.getSimpleName(entity);
			call.call();
		}
		
		public function deleteList(list:*, callback:Callback=null):void {
			var call:RemoteCall = delegate.deleteList(FlexUtils.collectionToArray(list)).addResponder(callback);
			call.description = "Deleting...";
			call.longDescription = "Deleting one or more items.";
			call.call();
		}
		
		public function search(search:Search, callback:Callback):void {
			var call:RemoteCall = delegate.search(search).addResponder(callback);
			call.description = "Searching...";
			call.longDescription = "Searching for some matching " + MetaDataUtils.getSimpleName(search.searchVO);
			call.call();
		}
		
		public function count(search:Search, callback:Callback):void {
			var call:RemoteCall = delegate.count(search).addResponder(callback);
			call.description = "Counting...";
			call.longDescription = "Counting matching " + MetaDataUtils.getSimpleName(search.searchVO);
			call.call();
		}
		
		public function searchAndCount(search:Search, callback:Callback):void {
			var call:RemoteCall = delegate.searchAndCount(search).addResponder(callback);
			call.description = "Searching...";
			call.longDescription = "Searching for some matching " + MetaDataUtils.getSimpleName(search.searchVO);
			call.call();
		}
		
		public function searchUnique(search:Search, callback:Callback):void {
			var call:RemoteCall = delegate.searchUnique(search).addResponder(callback);
			call.description = "Loading Data...";
			call.longDescription = "Searching for a specific " + MetaDataUtils.getSimpleName(search.searchVO);
			call.call();
		}
		
		public function fetchAllLazy(klass:Class, list:ArrayCollection=null, callback:Callback=null):ArrayCollection {
			if (list == null) list = new ArrayCollection();
			var call:RemoteCall = delegate.fetchAll(MetaDataUtils.getRemoteClass(klass))
				.addResponder(new Callback(fetchListSuccess, null, list, callback));
			call.description = "Loading Data...";
			call.longDescription = "Fetching all " + MetaDataUtils.getSimpleName(klass);
			call.call();
			return list;
		}
		
		public function fetchByIdLazy(klass:Class, id:int, object:Object=null, callback:Callback=null):Object {
			if (object == null) object = new klass();
			var call:RemoteCall = delegate.fetch(MetaDataUtils.getRemoteClass(klass), id)
				.addResponder(new Callback(fetchSingleSuccess, null, object, callback));
			call.description = "Loading Data...";
			call.longDescription = "Fetching a specific " + MetaDataUtils.getSimpleName(klass);
			call.call();
			return object;
		}
		
		public function searchLazy(search:Search, list:ArrayCollection=null, callback:Callback=null):ArrayCollection {
			if (list == null) list = new ArrayCollection();
			var call:RemoteCall = delegate.search(search).addResponder(new Callback(fetchListSuccess, null, list, callback));
			call.description = "Searching...";
			call.longDescription = "Searching for some matching " + MetaDataUtils.getSimpleName(search.searchVO);
			call.call();
			return list;
		}
		
		public function searchAndCountLazy(search:Search, callback:Callback=null):SearchResult {
			var result:SearchResult = new SearchResult();
			var call:RemoteCall = delegate.searchAndCount(search)
				.addResponder(new Callback(fetchSingleSuccess, null, result, callback));
			call.description = "Searching...";
			call.longDescription = "Searching for some matching " + MetaDataUtils.getSimpleName(search.searchVO);
			call.call();
			return result;
		}
		
		private function fetchSingleSuccess(data:*, object:*):void {
			FlexUtils.shallowCopy(data, object);
		}
		
		private function fetchListSuccess(data:*, list:*):void {
			list.source = data.source;
		}
		
	}
}